package com.eastdigit.shiro.filter;

import com.eastdigit.servlet.ReqBean;
import com.eastdigit.shiro.GlobalInput;
import com.eastdigit.shiro.authc.StateToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class StateAuthcFilter extends FormAuthenticationFilter {

    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        ReqBean reqBean = (ReqBean) request.getAttribute(ReqBean.NAME);
        String username = reqBean.getInfo("userCode");
        String password = reqBean.getInfo("password");
        String captcha = reqBean.getInfo("captcha");
        boolean rememberMe = "1".equals(reqBean.getInfo("rememberMe"));
        String host = getHost(request);
        return new StateToken(username, password == null ? null : password.toCharArray(), rememberMe, host, captcha);
    }

    @Override
    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
        if (!"OPTIONS".equals(((HttpServletRequest) request).getMethod())) {
            ((HttpServletResponse) response).sendError(871202);
        }
    }

    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
            ServletResponse response) throws Exception {
        // issueSuccessRedirect(request, response);
        RequestDispatcher rd = request.getRequestDispatcher(getSuccessUrl());
        rd.forward(request, response);
        return false;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (isLoginRequest(request, response)) {// 如果是登录请求，则返回false提交给登录校验，不然不重新登录
            return false;
        } else {
            Subject subject = this.getSubject(request, response);
            return subject.isAuthenticated();
        }
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,
            ServletResponse response) {
        // return super.onLoginFailure(token, e, request, response);
        request.setAttribute(getFailureKeyAttribute(), e);// 为了把异常Exception抛出去，本身抛出去的是对象的名称
        return true;
    }

    @Override
    protected void executeChain(ServletRequest request, ServletResponse response, FilterChain chain) throws Exception {
        // 验证通过，设置当前用户id
        if (!isLoginRequest(request, response)) {
            ReqBean reqBean = (ReqBean) request.getAttribute(ReqBean.NAME);
            if (reqBean != null) {// 这里可能没有经过MainFilter
                try {
                    reqBean.setUserId(GlobalInput.getCurrentUserId());
                } catch (Exception e) {
                    ((HttpServletResponse) response).sendError(871202);
                }
            }
        } else if (!SecurityUtils.getSubject().isAuthenticated()) {// 登录不成功，交给登录之后返回错误
            RequestDispatcher rd = request.getRequestDispatcher(getSuccessUrl());
            rd.forward(request, response);
            return;
        }
        super.executeChain(request, response, chain);
    }
}
